package com.interview.communication;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 【方式4】Lock + Condition
 * 现代的锁机制，比wait/notify更灵活
 * 可以有多个Condition对象，精细控制线程通信
 */
public class LockConditionExample {

    static class SharedBuffer {
        private String data;
        private boolean hasData = false;
        private final Lock lock = new ReentrantLock();
        private final Condition notEmpty = lock.newCondition();   // 缓冲区不为空
        private final Condition notFull = lock.newCondition();    // 缓冲区不满

        void put(String value) {
            lock.lock();
            try {
                // 如果已有数据，等待消费者消费
                while (hasData) {
                    notFull.await();
                }
                data = value;
                hasData = true;
                System.out.println("【生产】" + value);
                notEmpty.signalAll();  // 唤醒消费者
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            } finally {
                lock.unlock();
            }
        }

        String take() {
            lock.lock();
            try {
                // 如果没有数据，等待生产者生产
                while (!hasData) {
                    notEmpty.await();
                }
                String value = data;
                hasData = false;
                System.out.println("【消费】" + value);
                notFull.signalAll();  // 唤醒生产者
                return value;
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                return null;
            } finally {
                lock.unlock();
            }
        }
    }

    public static void demo() throws InterruptedException {
        SharedBuffer buffer = new SharedBuffer();

        Thread producer = new Thread(() -> {
            for (int i = 1; i <= 3; i++) {
                buffer.put("数据-" + i);
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        });

        Thread consumer = new Thread(() -> {
            for (int i = 0; i < 3; i++) {
                buffer.take();
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        });

        producer.start();
        consumer.start();

        producer.join();
        consumer.join();

        System.out.println("通信完成!");
    }
}

